home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
dev
/
c
/
vbcc.lha
/
vbcc
/
rd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-12-30
|
19KB
|
479 lines
/* $VER: vbcc (rd.c) V0.4 */
/* verfuegbare Definitionen und constant propagation */
#include "opt.h"
static char FILE_[]=__FILE__;
/* fuer verfuegbare Definitionen */
unsigned int dcount;
size_t dsize;
struct IC **dlist;
unsigned char **defs; /* gibt an, welche Definitionen, welche */
/* Variablen definieren */
/* alle Definitionen, globaler oder Adr. fuer propagation etc. */
unsigned char *rd_globals,*rd_address,*rd_statics,*rd_drefs;
/* dasseble, aber hier nur die undefs */
unsigned char *rd_defs,*rd_tmp,*rd_parms;
/* Bitvektor fuer geaenderte Variablen fuer ic_changes */
unsigned char *rd_vars;
/* rd_mode==0 => reaching definitions fuer constant-propagatione, */
/* sonst fuer loop-invariant. */
int rd_mode;
int compare_const(union atyps *q1,union atyps *q2,int t)
/* vergleiht zwei Konstanten; -1, wenn q1<q2; 0, wenn q1==q1; 1 sonst */
{
zdouble d1,d2;zlong l1,l2;zulong u1,u2;zpointer p1,p2;
t&=NU;
eval_const(q1,t);p1=vpointer;d1=vdouble;l1=vlong;u1=vulong;
eval_const(q2,t);p2=vpointer;d2=vdouble;l2=vlong;u2=vulong;
if(t==POINTER) return(zpleq(p2,p1)?!zpeqto(p1,p2):-1);
if(t==DOUBLE||t==FLOAT) return(zdleq(d2,d1)?!zdeqto(d1,d2):-1);
if(t&UNSIGNED) return(zulleq(u2,u1)?!zuleqto(u1,u2):-1);
return(zlleq(l2,l1)?!zleqto(l1,l2):-1);
ierror(0);
}
void print_rd(unsigned char *bitvector)
/* druckt Definitionen in einem Bitvektor */
{
unsigned int i;
if(!bitvector) {printf("reaching definitions not available\n");return;}
for(i=1;i<=dcount;i++)
if(BTST(bitvector,i)) {printf("%3u:",i);pric2(stdout,dlist[i]);}
for(i=0;i<vcount-rcount;i++)
if(BTST(bitvector,i+dcount+1)) printf("%3u:\t\tundefined\t->%s\n",i+dcount+1,vilist[i]->identifier);
for(i=vcount-rcount;i<vcount;i++)
if(BTST(bitvector,i+dcount+1)) printf("%3u:\t\tundefined\t->(%s)\n",i+dcount+1,vilist[i]->identifier);
}
void num_defs(void)
/* Numeriert alle Variablendefinitionen (nur elementare Typen noetig) */
/* und erzeugt diverse Bitvektoren. */
{
int i=0;struct IC *p;
if(DEBUG&1024) printf("numerating definitions\n");
for(p=first_ic;p;p=p->next){
if(!(p->z.flags&VAR)&&p->code!=CALL){p->defindex=0;continue;}
/* if((p->z.v->vtyp->flags&NQ)>POINTER){p->defindex=0;continue;}*/
p->defindex=++i;
}
dcount=i;dsize=(dcount+CHAR_BIT+vcount)/CHAR_BIT; /* +1, da bei 1 anfaengt */
if(DEBUG&1024) printf("%lu definitions, dsize=%lu\n",(unsigned long)dcount,(unsigned long)dsize);
/* fuer jede Variable wird eine kuenstliche unbestimmte Def. erzeugt */
/* Feld erzeugen, dass zu jeder Variable alle Definitionen erhaelt */
defs=mymalloc(sizeof(unsigned char *)*vcount);
for(i=0;i<vcount;i++){
defs[i]=mymalloc(dsize);
memset(defs[i],0,dsize);
BSET(defs[i],i+dcount+1);
}
dlist=mymalloc((dcount+1)*sizeof(struct IC *));
rd_globals=mymalloc(dsize);
memset(rd_globals,0,dsize);
rd_statics=mymalloc(dsize);
memset(rd_statics,0,dsize);
rd_address=mymalloc(dsize);
memset(rd_address,0,dsize);
rd_drefs=mymalloc(dsize);
memset(rd_drefs,0,dsize);
rd_vars=mymalloc(vsize);
for(p=first_ic;p;p=p->next){
if(p->defindex){
if(p->z.flags&VAR){
i=p->z.v->index;
if(p->z.flags&DREFOBJ) i+=vcount-rcount;
BSET(defs[i],p->defindex);
}
dlist[p->defindex]=p;
}
}
if(DEBUG&2048){
for(i=1;i<=dcount;i++){ printf("Def%3d: ",i);pric2(stdout,dlist[i]);}
for(i=0;i<vcount;i++){
printf("Definitionen fuer <%s>:\n",vilist[i]->identifier);
print_rd(defs[i]);
}
}
for(i=0;i<vcount-rcount;i++){ /* rd_globals berechnen */
if(vilist[i]->vtyp->flags&CONST) continue;
if(vilist[i]->nesting==0||vilist[i]->storage_class==EXTERN) bvunite(rd_globals,defs[i],dsize);
if(vilist[i]->flags&USEDASADR) bvunite(rd_address,defs[i],dsize);
if(vilist[i]->storage_class==STATIC) bvunite(rd_statics,defs[i],dsize);
if(i<rcount){
bvunite(rd_address,defs[i+vcount-rcount],dsize);
bvunite(rd_globals,defs[i+vcount-rcount],dsize);
bvunite(rd_drefs,defs[i+vcount-rcount],dsize);
}
}
rd_parms=mymalloc(dsize);
memset(rd_parms,0,dsize);
for(i=0;i<vcount;i++){
struct Var *v=vilist[i];
if(i>=vcount-rcount||zl2l(v->offset)<0||(v->flags®PARM)||v->nesting==0||v->storage_class==EXTERN||v->storage_class==STATIC){
BSET(rd_parms,i+dcount+1);
}
}
/* if(DEBUG&1024){printf("rd_globals:\n");print_rd(rd_globals);}*/
}
int complete_def(struct IC *p)
/* Testet, ob eine Definition die Zielvariable komplett setzt oder nur */
/* teilweise. */
{
struct Typ *t=p->z.v->vtyp;
zlong s1,s2;
if(p->z.flags&DREFOBJ) t=t->next;
if(!t) return(0);
s1=szof(t);
if(p->code==ASSIGN||p->code==GETRETURN) s2=p->q2.val.vlong;
else s2=sizetab[p->typf&NQ];
/* if(s1<s2) ierror(0);*/
if(zleqto(s1,s2)) return(1); else return(0);
}
void reaching_definitions(struct flowgraph *fg)
/* Berechnet die verfuegbaren Definitionen fuer jeden Block. */
{
struct flowgraph *g;struct IC *p;unsigned char *tmp;
int changed,pass,i,j;
/* rd_gen und rd_kill fuer jeden Block berechnen */
if(DEBUG&1024) printf("analysing reaching definitions\n");
tmp=mymalloc(dsize);
g=fg;
while(g){
g->rd_in=mymalloc(dsize);
memset(g->rd_in,0,dsize);
g->rd_out=mymalloc(dsize);
memset(g->rd_out,0,dsize);
g->rd_gen=mymalloc(dsize);
memset(g->rd_gen,0,dsize);
g->rd_kill=mymalloc(dsize);
memset(g->rd_kill,0,dsize);
p=g->end;
while(p){
if(p->defindex){
int zi=-1;
if(!BTST(g->rd_kill,p->defindex)) BSET(g->rd_gen,p->defindex);
if(p->z.flags&VAR){
if(!BTST(g->rd_kill,p->defindex)&&complete_def(p)){
zi=p->z.v->index;
if(p->z.flags&DREFOBJ) zi+=vcount-rcount;
memcpy(tmp,defs[zi],dsize);
bvdiff(tmp,g->rd_gen,dsize);
bvunite(g->rd_kill,tmp,dsize);
}
}
for(j=0;j<p->change_cnt;j++){
i=p->change_list[j].v->index;
if(p->change_list[j].flags&DREFOBJ) i+=vcount-rcount;
if(i>=vcount) continue;
if((i!=zi||(p->typf&NQ)>POINTER)&&!BTST(g->rd_kill,i+dcount+1)){
BSET(g->rd_gen,i+dcount+1);
if(i<rcount&&!BTST(g->rd_kill,dcount+1+i+vcount-rcount))
BSET(g->rd_gen,i+vcount-rcount+dcount+1);
}
}
}
if(p==g->start) break;
p=p->prev;
}
memcpy(g->rd_out,g->rd_gen,dsize);
g=g->normalout;
}
/* rd_in und rd_out fuer jeden Block berechnen */
/* out(b)=gen(B) vorinitialisiert */
if(DEBUG&1024) {printf("pass:");pass=0;}
do{
if(DEBUG&1024) {printf(" %d",++pass);fflush(stdout);}
changed=0;
g=fg;
while(g){
struct flowlist *lp;
/* in(B)=U out(C) : C Vorgaenger von B */
if(g==fg) memcpy(g->rd_in,rd_parms,dsize);
else memset(g->rd_in,0,dsize);
lp=g->in;
while(lp){
if(!lp->graph) ierror(0);
if(lp->graph->branchout==g||!lp->graph->end||lp->graph->end->code!=BRA)
bvunite(g->rd_in,lp->graph->rd_out,dsize);
lp=lp->next;
}
/* out(b)=gen(B) U (in(B)-kill(B) */
memcpy(tmp,g->rd_in,dsize);
bvdiff(tmp,g->rd_kill,dsize);
bvunite(tmp,g->rd_gen,